昨天我們建立了Component做為SPA裡的頁面之後,再來要建立一種方式,可以動態判斷網址與對應的頁面元件,SPA中的路由(Router)與路徑(Route)就是扮演這樣的角色,前面的主題也提過三大框架有自己的Router,接著就來嘗試用原生Javascript手動建立吧!
Route:路徑,每個Component事先設定對應的網址路徑
Router:路由,判斷符合設定的路徑並匹配對應的Component
可以想像你正要準備搭火車前往桃園,過程中會先去自動售票機買票,投了錢按下目的地桃園站,就會拿到車票。Route就像是事先設定在自動售票機裡的程式,按下某個目的地會對應前往某處的車票;而Router就像是自動售票機本身,處理你投錢按下目的地及拿到車票整個過程。
在client side產生render的過程,需要一個有效的判斷與管理方式。我們可以透過事先建立好Route,並設定對應的Component,然後經由Router判斷對應的Component後,再render產生畫面。
先來參考看看React路由的結構:
<Router>
<Switch>
<Route exact path="/home">
<Home />
</Route>
</Switch>
</Router>
Router包在最外層,Route包在Component的外層,其中在Route有個path參數指向/home,當網址後面的路徑是/home時,就會切換並對應到此路徑下的Home元件,如果要對應多個路徑,只要新增Route和給予對應的path,然後一樣包著需要對應的元件就可以了,了解後我們就來嘗試著建立模組。
src目錄下建立routes目錄,然後在routes目錄裡建立Route.js,設定路徑與對應的Component。
src/routes/Route.js:
//引入Component
import { Home } from '../pages/Home'
export const Route = [
{ path: '/', component: Home },
]
開頭我們把昨天建立的Component物件引入,然後宣告Route為一個陣列(array),每個物件元素裡給予對應的路徑(path)與載入的元件(component)屬性,最後把Route當作模組匯出,提供給Router使用判斷。為了方便之後看出效果,可以再試試增加一個物件元素在Route陣列裡:
src/routes/Route.js:
//引入Component
import { Home } from '../pages/Home'
import { Post } from '../pages/Post'
export const Route = [
{ path: '/', component: Home },
{ path: '/post', component: Post }, //在src/pages裡增加Post.js頁面
]
仔細看Route第一個物件元素的component屬性為「Home」,path屬性為「/」,代表目前路徑為根目錄時,會對應到Home元件的內容。而SPA實際上是如何以client side方式得到目前路徑呢? 複習一下,前面SPA實做有使用history和hash的方式,這邊使用簡單直接的hash。當想要知道目前完整網址,可以用location.href方法得知,但Router判斷路徑其實只要hash的部份,所以可以用location.hash得到路徑資訊,並與Route每個物件元素的path屬性做比對。
舉個例子:
假設網址是 localhost ,這時還沒有hash值,我們可以透過點擊超連結在網址後面加上「#/」,這時網址會變成localhost/#/,對應的頁面是Home;而當我們網址列後面加上「#/post」,這時網址會變成localhost/#/post,對應的頁面是Post,可以想像匹配路由的情形會是下面這樣:
localhost/#/ => location.hash得到「#/」,對應元件為Home。
localhost/#/post => location.hash得到「#/post」,對應元件為Post。
然後只要把 location.hash的值去掉「#」,就能正確對應到Route陣列元素裡的path屬性,只要得知對應到哪個元素,自然就能找出對應component了。不過聰明的你應該會發現一件事,不對阿?一開始網址本來就沒有hash值不是嗎?這樣能夠對應到Home頁面嗎?
想像情境:
localhost => location.hash為空值,對應不到任何path
「???」
要如何解決這個問題?這邊先賣個關子,如果有注意前面的文章,相信馬上就會知道答案了,明天我們將會繼續談這個部份,並且完成Router的實做。
參考資料:
Build a very basic SPA JavaScript router